Bist du dir sicher, dass deine Hauptprogrammschleife länger braucht, als 1/50 Sekunde, der Zeit zwischen zwei VBIs?
Teste es doch einfach mal:
Lies RTCLOK+2 am Beginn und Ende deiner Schleife aus und vergleich die Werte. Dann siehst du, wieviele VBIs dazwischen vergangen sind weil RTCLOK+2 innerhalb jedes VBIs inkrementiert wird.
Das Zeitproblem im VBI ist ja nicht, dass du die 1/50 Sekunde überschreitest, sondern dass du innerhalb des VBIs nur den kurzen Zeitraum hast, den der (vermutlich inzwischen virtuelle) Kathodenstrahl benötigt, um von rechts unten nach links oben geschwenkt zu werden.
Du hast zwei Möglichkeiten, dich zu synchronisieren.
Entweder für die komplette Hauptschleife, was sinnvoll ist, wenn sie deutlich weniger Zeit benötigt, als die 1/50 Sekunde und du nicht willst, dass sie schneller abläuft.
Oder, wie in meinem Beispiel im anderen Thread, du baust die Dinge, die gezielt innerhalb jeder 1/50 Sekunde einmal (aber nicht exakt synchron, wie im VBI) passieren müssen, in ein Unterprogramm ein, das du (ggf. auch mehrfach) aus deinem Hauptprogramm aufrufst.
Da passen z.B. die Kollisionsabfragen rein oder auch Änderungen auf dem gerade nicht sichtbaren Bildschirm, falls du mittels Page-Flipping bzw. Double-Buffering arbeitest.
Der mehrfache Einbau der Unterprogramme hat dann Sinn, wenn dein Hauptprogramm tatsächlich mehr Zeit verschlingt, als 1/50 Sekunde.
Mini-Codebeispiel für die Variante Hauptschleife:
; Programmbeginn
; Hauptschleife
main
lda RTCLOK+2
sta startzeit ; Ein Byte, das du irgendwo allokiert hast.
; Hier kommt deine Hauptschleife mit all den zeitaufwändigen Aufgaben rein.
; Warte darauf, dass der VBI ausgeführt wird.
; Falls der Schleifendurchlauf langsamer war, geht's direkt weiter weil RTCLOK+2 bereits inkrementiert wurde.
lda startzeit
warte
cmp RTCLOK+2
beq warte
; Und es geht von vorne los.
jmp main
Mini-Codebeispiel für die Variante Unterprogramm (analog zum RtP Thread) minimal erweitert:
Die Unterprogramme steuer dabei selbst, dass sie zwischen zwei VBIs nur einmal ausgeführt werden. Jeder weitere Aufruf innerhalb dieser Zeit führt zu einem direkten RTS.
; Programmbeginn
; Stell einen definierten Anfangszustand her.
; Ansonsten kann es sein, dass der erste Durchlauf stottert.
lda RTCLOK+2
sta letzter_durchlauf1 ; Ein Byte, das du irgendwo allokiert hast.
sta letzter_durchlauf2
; und ggf. für weitere Unterprogramme
; Hauptschleife
main
; Wieder deine Hauptschleife mit all den zeitaufwändigen Aufgaben.
jsr tue_dieses
jsr kollisionen ; VBI-synchronisiert
jsr bildschirmaufbau_double_buffer ; VBI synchronisiert
jsr tue_jenes
jsr mach_was_tolles ; das ganz lang dauert
jsr kollisionen ; VBI-synchronisiert; ein zweites Mal, falls "mach_was_tolles" zu lange gebraucht hat
jsr bildschirmaufbau_double_buffer ; VBI synchronisiert
; Und es geht von vorne los.
jmp main
kollisionen
lda RTCLOK+2 ; wird im Stage 1 VBI automatisch inkrementiert
cmp letzter_durchlauf1
bne mach_weiter1
rts
mach_weiter1
sta letzter_durchlauf1
; Berechne die Kollisionen und merk die Ergebnisse für die Umsetzung im VBI
rts
bildschirmaufbau_double_buffer
lda RTCLOK+2 ; wird im Stage 1 VBI automatisch inkrementiert
cmp letzter_durchlauf2
bne mach_weiter2
rts
mach_weiter2
sta letzter_durchlauf2
; Bau denzweiten Bildschirm auf, dass du im VBI umschalten kannst.
rts